package com.alibaba.cirtus.ots.application.adapter.ability.facade.service.sap;

import com.alibaba.cirtus.ots.application.adapter.ability.model.request.OccupyOccupyReleaseRequest;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.InfoUtil;
import com.alibaba.cirtus.ots.application.adapter.ability.utils.ResponseUtil;
import com.alibaba.citrus.ots.common.annotation.ProcessInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.lock.RedisLock;
import com.alibaba.citrus.ots.common.util.IntegrateUtils;
import com.alibaba.citrus.ots.common.util.SapAndCrmFieldDealUtils;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.otsapplicationadaptersdk.model.dto.SapRetrySaveRequest;
import com.epoch.app.otsapplicationadaptersdk.model.enums.RetryStatus;
import com.epoch.app.otsapplicationadaptersdk.model.enums.SapApiCode;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommDetail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommResponse;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapCommSDO;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf017Detail;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf017Request;
import com.epoch.app.otsapplicationadaptersdk.sap.MnSapIf017SDO;
import com.epoch.app.otsapplicationadaptersdk.sap.mnsapif017.service.MnSapIf017Service;
import com.epoch.app.otsapplicationadaptersdk.sapretrywrite.service.SapRetryWriteService;
import com.epoch.app.otsb2btradecenter.domain.order.dto.LoadOrderListRequest;
import com.epoch.app.otsb2btradecenter.domain.order.dto.LoadOrderRequest;
import com.epoch.app.otsb2btradecenter.domain.order.model.Order;
import com.epoch.app.otsb2btradecenter.domain.order.service.OrderService;
import com.epoch.app.otsb2btradecenter.domain.orderline.dto.OrderLineLoadListRequest;
import com.epoch.app.otsb2btradecenter.domain.orderline.model.OrderLine;
import com.epoch.app.otsb2btradecenter.domain.orderline.service.OrderLineService;
import com.epoch.app.otsb2btradecenter.enums.OrderStatus;
import com.epoch.app.otsunifiedinventory.api.allocateorderwrite.service.AllocateOrderWriteService;
import com.epoch.app.otsunifiedinventory.api.consignmentorderwrite.service.ConsignmentOrderWriteService;
import com.epoch.app.otsunifiedinventory.consignmentorder.dto.LoadConsignmentOrderRequest;
import com.epoch.app.otsunifiedinventory.consignmentorder.model.ConsignmentOrder;
import com.epoch.app.otsunifiedinventory.consignmentorder.service.ConsignmentOrderService;
import com.epoch.app.otsunifiedinventory.consignmentorderline.model.ConsignmentOrderLine;
import com.epoch.app.otsunifiedinventory.consignmentorderline.service.ConsignmentOrderLineService;
import com.epoch.app.otsunifiedinventory.domain.allocateorder.dto.AllocateOrderLoadListRequest;
import com.epoch.app.otsunifiedinventory.domain.allocateorder.model.AllocateOrder;
import com.epoch.app.otsunifiedinventory.domain.allocateorder.service.AllocateOrderService;
import com.epoch.app.otsunifiedinventory.dto.request.AllocateOrderDeliveryScItemDTO;
import com.epoch.app.otsunifiedinventory.dto.request.ConsignmentOrderWriteCreateRequest;
import com.epoch.app.otsunifiedinventory.model.dto.AllocateOrderDeliveryRequest;
import com.epoch.app.otsunifiedinventory.model.dto.ConsignmentOrderLineLoadListRequest;
import com.epoch.app.otsunifiedinventory.model.dto.ConsignmentOrderLineRequest;
import com.epoch.app.otsunifiedinventory.model.dto.ConsignmentOrderLoadListRequest;
import com.epoch.app.otsunifiedinventory.model.dto.InvOperateLine;
import com.epoch.app.otsunifiedinventory.model.dto.OccupyReleaseRequest;
import com.epoch.app.otsunifiedinventory.model.dto.OccupyReleaseResponse;
import com.epoch.app.otsunifiedinventory.model.dto.OccupyRequest;
import com.epoch.app.otsunifiedinventory.model.dto.OccupyResponse;
import com.epoch.app.otsunifiedinventory.model.dto.WmsSDO;
import com.epoch.app.otsunifiedinventory.sdo.enums.ReasonForRejectionEnum;
import com.epoch.app.otsunifiedinventory.service.OtsUnifiedInventoryService;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import tools.Pair;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@Primary
public class MnSapIf017ServiceImpl implements MnSapIf017Service {
    private static final Log LOG = Log.getLogger(MnSapIf017ServiceImpl.class);
    public static final String SPEC_ORG = "1171";

    @Resource
    private ConsignmentOrderWriteService consignmentOrderWriteService;
    @Resource
    private AllocateOrderWriteService allocateOrderWriteService;

    private final static List<String> saleOrderExtList=Lists.newArrayList("ZORO","ZORA","ZRE5");
    //退货销售单类型 不预占库存
    private final static List<String> returnGoodsExtList = Lists.newArrayList("ZRE2","ZRE3");
    @Resource
    private SapRetryWriteService sapRetryWriteService;
    @Resource
    private AllocateOrderService allocateOrderService;
    @Resource
    private OrderService orderService;
    @Resource
    private BaseDataService baseDataService;
    @Resource
    private EpochCacheService epochCacheService;
    @Resource
    private OtsUnifiedInventoryService otsUnifiedInventoryService;
    @Resource
    private ConsignmentOrderService consignmentOrderService;
    @Resource
    private ConsignmentOrderLineService consignmentOrderLineService;
    @Resource
    private OrderLineService orderLineService;

    public static final String EXCHANGE= "exchange";
    private static final String EXCHANGE_ORDER_TYPE = "ZCH2";

    private static final String DELIVERY_ORDER_CACHE_KEY = "DELIVERY_ORDER_CACHE_KEY_";
    private static final String DELIVERY_ORDER_LOCK = "DELIVERY_ORDER_LOCK_";
    //设置sap过期时间为
    private static final Long SAP_TIMESTAMP_CACHE_EXPIRE = 60 * 60 * 24 * 100L;
    @Value("${ots.checkTimestamp:0}")
    private boolean checkTimestamp;

    @Override
    @ProcessInvoker(remark = "MnSapIf017Service", errorCode = "", printLog = true)
    public MnSapCommResponse externalSyncDeliveryOrder(MnSapIf017Request mnSapIf017Request) {
        MnSapCommResponse mnSapCommResponse = new MnSapCommResponse();

        // Try to get from mogodb if null
        if (mnSapIf017Request == null) {
            mnSapIf017Request = IntegrateUtils.safeGetMessageObject(MnSapIf017Request.class);
        }

        mnSapCommResponse.setMessageId(mnSapIf017Request.getMessageHeader().getMessageId());
        mnSapCommResponse.setInterfacePath(mnSapIf017Request.getMessageHeader().getInterfacePath());

        List<MnSapCommSDO> respData = new ArrayList<>();
        for (MnSapIf017SDO datum : mnSapIf017Request.getData()) {
            if (checkTimestamp){
                String check = ResponseUtil.check(datum.getExt1());
                if (StringUtils.isNotBlank(check)){
//                    saveSapRetry(mnSapIf017Request,check);
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDO.setMessage(check);
                    mnSapCommSDO.setHeaderKey(datum.getHeaderKey());
                    List<MnSapCommDetail> commDetails = new ArrayList<>();
                    MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                    mnSapCommDetail.setStatus("E");
                    mnSapCommDetail.setMessage(check);
//                mnSapCommDetail.setItemKey(item.getItem_key());
                    commDetails.add(mnSapCommDetail);
                    mnSapCommSDO.setItem(commDetails);
                    respData.add(mnSapCommSDO);
                    mnSapCommResponse.setData(respData);
                    return mnSapCommResponse;
                }
                boolean checkModifierTime = checkModifierTime(datum);
                if (!checkModifierTime){
                    //时间戳校验不通过需要抛错 放入重试表
                    saveSapRetry(mnSapIf017Request,"当前修改时间早于上一次 不允许更新");
                    MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDO.setMessage("当前修改时间早于上一次 不允许更新");
                    mnSapCommSDO.setHeaderKey(datum.getHeaderKey());
                    List<MnSapCommDetail> commDetails = new ArrayList<>();
                    MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                    mnSapCommDetail.setStatus("E");
                    mnSapCommDetail.setMessage("当前修改时间早于上一次 不允许更新");
//                mnSapCommDetail.setItemKey(item.getItem_key());
                    commDetails.add(mnSapCommDetail);
                    mnSapCommSDO.setItem(commDetails);
                    respData.add(mnSapCommSDO);
                    mnSapCommResponse.setData(respData);
                    return mnSapCommResponse;
                }else {
                    //校验通过就要放入时间戳
//                    cache(datum.getDeliveryOrderId(),datum.getExt());
                }

            }

            //销售单是否需要预占库存
            boolean occupyFlg = false;
            String salesOrderId = null;

            ConsignmentOrderWriteCreateRequest request = new ConsignmentOrderWriteCreateRequest();
            request.setOuterDeliveryOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getDeliveryOrderId()));
            request.setOuterSalesOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getSalesOrderId()));
            request.setSalesOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getOuterSalesOrderId()));
            request.setOuterStoOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getStoOrderId()));
            request.setCreator(SapAndCrmFieldDealUtils.generateIdField(datum.getCreator()));
            request.setModifier(SapAndCrmFieldDealUtils.generateIdField(datum.getModifier()));
//            BaselineGetOrganizationByOutCodesRequest orgRequset = new BaselineGetOrganizationByOutCodesRequest();
//            orgRequset.setOutCodes(Lists.newArrayList(SapAndCrmFieldDealUtils.generateIdField(datum.getSalesOrgId())));
//            Map saleOrgMap = externalSyncDeliveryOrder$callAPI2(orgRequset);
//            JSONArray saleJsonArray = JSONObject.parseObject(JSONObject.toJSONString(saleOrgMap)).getJSONArray("result");
//            if (CollectionUtils.isEmpty(saleJsonArray)) {
//                List<MnSapCommSDO> sdos = new ArrayList<>();
//                MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
//                mnSapCommSDO.setStatus("E");
//                mnSapCommSDO.setMessage("销售组织信息转换失败");
//                mnSapCommSDO.setErrCode("999");
//                mnSapCommSDO.setHeaderKey(datum.getHeaderKey());
//                sdos.add(mnSapCommSDO);
//                mnSapCommResponse.setData(sdos);
//                return mnSapCommResponse;
//            }
//            JSONObject organizationSDO = saleJsonArray.getJSONObject(0).getJSONObject("organizationSDO");
//            request.setSalesOrgId(organizationSDO.getString("id"));
            request.setSalesOrgId(datum.getSalesOrgId());
            request.setStoOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getOuterStoOrderId()));
            request.setCreator(datum.getCreator());
            request.setCreatDate(SapAndCrmFieldDealUtils.toDate(datum.getCreatDate()));
            request.setModifier(datum.getModifier());
            request.setModifidDate(SapAndCrmFieldDealUtils.toDate(datum.getModifidDate()));
            request.setDeliveryDate(SapAndCrmFieldDealUtils.toDate(datum.getDeliveryDate()));
            request.setFeatures(datum.getFeatures());

            //013接口会同步特殊的销售单，判断ext=ZORO且销售组织是1171的交货单，修改为销售订单类型的交货单
            if ((StringUtils.isNotBlank(datum.getExt())&&saleOrderExtList.contains(datum.getExt()))&&(
                    StringUtils.isNotBlank(datum.getSalesOrgId())&& SPEC_ORG.equalsIgnoreCase(datum.getSalesOrgId())
                    )){
                request.setOuterSalesOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getStoOrderId()));
            }

            //开始处理明细
            MnSapCommSDO mnSapCommSDO = new MnSapCommSDO();
            mnSapCommSDO.setStatus("S");
            mnSapCommSDO.setMessage("成功");
            mnSapCommSDO.setHeaderKey(datum.getHeaderKey());
            List<MnSapCommDetail> details = new ArrayList<>();
            List<AllocateOrderDeliveryScItemDTO> scItemDTOList = Lists.newArrayList();
            List<ConsignmentOrderLineRequest> collect = new ArrayList<>();
            for (MnSapIf017Detail item : datum.getItems()) {
                ConsignmentOrderLineRequest lineRequest = new ConsignmentOrderLineRequest();
                lineRequest.setOuterOrderLineId(SapAndCrmFieldDealUtils.generateIdField(item.getOrderLineId()));
                lineRequest.setOuterSoLineId(SapAndCrmFieldDealUtils.generateIdField(item.getSoLineId()));
                lineRequest.setSoLineId(SapAndCrmFieldDealUtils.generateIdField(item.getOuterSoLineId()));
                lineRequest.setOuterStoLineId(SapAndCrmFieldDealUtils.generateIdField(item.getStoLineId()));
                lineRequest.setStoLineId(SapAndCrmFieldDealUtils.generateIdField(item.getStoLineId()));
                if ((StringUtils.isNotBlank(datum.getExt())&&saleOrderExtList.contains(datum.getExt()))&&(
                        StringUtils.isNotBlank(datum.getSalesOrgId())&& SPEC_ORG.equalsIgnoreCase(datum.getSalesOrgId())
                )){
                    lineRequest.setOuterSoLineId(SapAndCrmFieldDealUtils.generateIdField(item.getStoLineId()));
                }

                //2022.05.19 因为定时器里用callAPI报错了 会引起未知的问题 所以callAPI放弃使用
                String scItemId = InfoUtil.getScItemIdByOutCode(SapAndCrmFieldDealUtils.generateScItemIdField(item.getScItemId()));
                if (StringUtils.isBlank(scItemId)){
                    LOG.error("MnSapIf017ServiceImpl_scItemConvertError:{}",item.getScItemId());
                    mnSapCommSDO.setStatus("E");
                    mnSapCommSDO.setMessage(item.getScItemId()+" 货品编码转换失败");
                    mnSapCommSDO.setHeaderKey(datum.getHeaderKey());
                    List<MnSapCommDetail> commDetails = new ArrayList<>();
                    MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                    mnSapCommDetail.setStatus("E");
                    mnSapCommDetail.setMessage(item.getScItemId()+" 货品编码转换失败");
                    mnSapCommDetail.setItemKey(item.getItem_key());
                    commDetails.add(mnSapCommDetail);
                    mnSapCommSDO.setItem(commDetails);
                    respData.add(mnSapCommSDO);
                    mnSapCommResponse.setData(respData);
                    saveSapRetry(mnSapIf017Request,item.getScItemId()+" 货品编码转换失败");
                    return mnSapCommResponse;
                }
//                JSONObject scItemJson = scItemJsonArray.getJSONObject(0);
                lineRequest.setScItemId(scItemId);
                lineRequest.setQty(item.getQty());
                lineRequest.setPodStatus(item.getPodStatus());
                lineRequest.setPodQty(item.getPodQty());
                lineRequest.setFactoryCode(item.getFactoryCode());
                lineRequest.setInventoryCode(item.getInventoryCode());
                lineRequest.setSaleUnit(item.getSaleUnit());
                lineRequest.setBasicQuantity(item.getBasicQuantity());
                collect.add(lineRequest);

                AllocateOrderDeliveryScItemDTO scItemDTO = new AllocateOrderDeliveryScItemDTO();
                scItemDTO.setScItemCode(subStringScItmCode(item.getScItemId()));
                scItemDTO.setDeliveryQuantity(item.getQty());
                //文档 和数据库 是反着来的 此处指报文里的stoLineId为调拨单的外部行号 去掉前缀0
                scItemDTO.setOutAllocateOrderLineId(InfoUtil.deleteZeroPrefix(item.getStoLineId()));
//                scItemDTO.setOutAllocateOrderLineId(item.getOuterStoLineId());
                scItemDTOList.add(scItemDTO);

                MnSapCommDetail mnSapCommDetail = new MnSapCommDetail();
                mnSapCommDetail.setStatus("S");
                mnSapCommDetail.setMessage("成功");
                mnSapCommDetail.setItemKey(item.getItem_key());
                details.add(mnSapCommDetail);
                mnSapCommSDO.setItem(details);
            }
            respData.add(mnSapCommSDO);

            request.setConsignmentOrderLineRequest(collect);
            //2022.05.18 如果查询不到调拨单/销售单 那么就需要重试
            if (StringUtils.isNotBlank(request.getOuterSalesOrderId())){
                LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
                //此处不能去0 因为销售单里的外部单号存了0
                loadOrderListRequest.setOuterOrderId(datum.getStoOrderId());
                Result<List<Order>> listResult = orderService.loadOrderList(loadOrderListRequest);
                if (Objects.isNull(listResult) || CollectionUtils.isEmpty(listResult.getResult())){
                    saveSapRetry(mnSapIf017Request,"交货单查询不到销售单");
                    return ResponseUtil.fail(mnSapIf017Request,"交货单查询不到销售单");
                }
                //是销售单需要进行库存预占逻辑
                occupyFlg = true;
                salesOrderId = String.valueOf(listResult.getResult().get(0).getId());
            }else if (StringUtils.isNotBlank(datum.getStoOrderId())){
                AllocateOrderLoadListRequest allocateOrderLoadListRequest = new AllocateOrderLoadListRequest();
                allocateOrderLoadListRequest.setOutAllocateOrderId(datum.getStoOrderId());
                Result<List<AllocateOrder>> loadAllocateOrderList = allocateOrderService.loadAllocateOrderList(allocateOrderLoadListRequest);
                if (loadAllocateOrderList == null || CollectionUtils.isEmpty(loadAllocateOrderList.getResult())){
                    saveSapRetry(mnSapIf017Request,"交货单查询不到调拨单");
                    return ResponseUtil.fail(mnSapIf017Request,"交货单查询不到调拨单");
                }
            }

            boolean isSaleOrder = isSaleOrder(datum);

            //交货单落库前 查库里是否有交货单 (第一次创建交货单 库里没有交货单 需要查询销售单明细 后面作为封装释放库存请求源)
            List<ConsignmentOrder> loadConsignmentOrderList = null;
            List<ConsignmentOrderLine> consignmentOrderLines = null;
            List<OrderLine> orderLineList = null;
            Order targetOrder = null;
            if (isSaleOrder){
                try {
                    ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
                    //去掉前缀0
                    consignmentOrderLoadListRequest.setOuterDeliveryOrderId(SapAndCrmFieldDealUtils.generateIdField(datum.getDeliveryOrderId()));
                    consignmentOrderLoadListRequest.setStatus(1);
                    Result<List<ConsignmentOrder>> loadConsignmentOrderListResult = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
                    if (!Objects.isNull(loadConsignmentOrderListResult) && CollectionUtils.isNotEmpty(loadConsignmentOrderListResult.getResult())) {
                        ConsignmentOrder consignmentOrder = loadConsignmentOrderListResult.getResult().get(0);
                        ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
                        consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
                        Result<List<ConsignmentOrderLine>> listResult = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
                        if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())) {
                            consignmentOrderLines = listResult.getResult();
                        }
                    }
                    LoadOrderRequest loadOrderRequest = new LoadOrderRequest();
                    loadOrderRequest.setId(salesOrderId);
                    Order order = orderService.loadOrder(loadOrderRequest);
                    targetOrder = order;
                    if (CollectionUtils.isEmpty(consignmentOrderLines)) {
                        if (order != null){
                            //换货只取换货的行 且非关闭的
                            if (EXCHANGE_ORDER_TYPE.equals(order.getOrderType())){
                                OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                                orderLineLoadListRequest.setMainOrderId(salesOrderId);
                                Result<List<OrderLine>> lineResult = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                                if (lineResult != null && CollectionUtils.isNotEmpty(lineResult.getResult())){
                                    orderLineList = lineResult.getResult().stream().filter(x->EXCHANGE.equals(x.getOrderLineTag()) &&
                                            !ReasonForRejectionEnum.Z1.getCode().equals(x.getRefuseReasonCode()))
                                            .collect(Collectors.toList());
                                }
                            }else {
                                OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                                orderLineLoadListRequest.setMainOrderId(salesOrderId);
                                Result<List<OrderLine>> lineResult = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                                if (lineResult != null && CollectionUtils.isNotEmpty(lineResult.getResult())){
                                    orderLineList = lineResult.getResult().stream().filter(x->!ReasonForRejectionEnum.Z1.getCode().equals(x.getRefuseReasonCode()))
                                            .collect(Collectors.toList());
                                }

                            }

                        }
                    }
                } catch (Exception e) {
                    //error
                    LOG.error("MnSapIf017ServiceImpl_loadConsignmentOrderList_error",e);
                }
            }


            try{
                consignmentOrderWriteService.create(request);
            }catch (Throwable e){
                LOG.error("MnSapIf017ServiceImpl_create_error",e);
                saveSapRetry(mnSapIf017Request,"交货单更新异常");
                return ResponseUtil.fail(mnSapIf017Request,"交货单更新异常");
            }
            // TBD 这里的异常处理和返回值处理需要优化，除非确定是弱依赖，
            try {
                AllocateOrderDeliveryRequest allocateOrderDeliveryRequest = new AllocateOrderDeliveryRequest();
                allocateOrderDeliveryRequest.setCode(datum.getOuterStoOrderId());
                if (StringUtils.isNotBlank(datum.getStoOrderId())){
                    allocateOrderDeliveryRequest.setOutAllocateOrderId(datum.getStoOrderId());
                }
                allocateOrderDeliveryRequest.setDeliveryDate(datum.getDeliveryDate());
                //实际用这个作为交货日期
                allocateOrderDeliveryRequest.setCreateDate(datum.getCreatDate());
                //更改调拨单的交货数量
                allocateOrderDeliveryRequest.setDeliveryScItemDTOList(scItemDTOList);
                allocateOrderWriteService.delivered(allocateOrderDeliveryRequest);
            } catch (Exception e) {
                LOG.error("MnSapIf017Service.externalSyncDeliveryOrder error", e);
            }
            //如果是销售单 需要处理预占
            List<ConsignmentOrderLine> freshLines = Lists.newArrayList();
            if (isSaleOrder){
                String deliveryOrderId = SapAndCrmFieldDealUtils.generateIdField(datum.getDeliveryOrderId());
                ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
                consignmentOrderLoadListRequest.setOuterDeliveryOrderId(deliveryOrderId);
                consignmentOrderLoadListRequest.setStatus(1);
                Result<List<ConsignmentOrder>> listResult = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
                if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
                    ConsignmentOrder consignmentOrder = listResult.getResult().get(0);
                    ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
                    consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
                    Result<List<ConsignmentOrderLine>> result = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
                    if (result != null && CollectionUtils.isNotEmpty(result.getResult())){
                        freshLines = result.getResult();
                    }
                }
                try(RedisLock lock = new RedisLock(BcOtsConstants.REDIS_CACHE_CODE(),DELIVERY_ORDER_LOCK + SapAndCrmFieldDealUtils.generateIdField(datum.getDeliveryOrderId()),
                        5 * 60 * 1000,10 * 60 * 1000)){
                    if (!lock.lock()){
                        //写入重试表
                        saveSapRetry(mnSapIf017Request,"获取分布式锁错误");
                        return ResponseUtil.fail(mnSapIf017Request,"交货单更新异常");
                    }
                    if (occupyFlg) {
//                    salesOrderInvOccupy(datum,consignmentOrderLines,orderLineList);
                    }
                    handleInventory(datum,consignmentOrderLines,freshLines,orderLineList,targetOrder.getDeliveryStatus());

                }catch (Throwable e){
                    e.printStackTrace();
                    LOG.error("DelDeliveryOrderLockError:{},exception:{}", JSON.toJSONString(mnSapIf017Request),e);
                    //写入重试表
                    saveSapRetry(mnSapIf017Request,e.getMessage());
                    return ResponseUtil.fail(mnSapIf017Request,e.getMessage());
                }
            }



            //如果需要校验且校验通过
            if (checkTimestamp){
                cache(datum.getDeliveryOrderId(),datum.getExt1());
            }
        }


        mnSapCommResponse.setData(respData);
        return mnSapCommResponse;
    }

    /**
     * 截取scItemCode 固定长度为12
     * @param str
     * @return
     */
    public static String subStringScItmCode(String str){
        if (StringUtils.isBlank(str)){
            return null;
        }
        if (str.length()>12){
            return str.substring(str.length()-12);
        }
        return str;
    }
    public void saveSapRetry(MnSapIf017Request request,String message) {
        try {
            if (request == null || StringUtils.isBlank(message)) {
                return;
            }
            MnSapIf017SDO sdo = request.getData().get(0);
            SapRetrySaveRequest sapRetrySaveRequest = new SapRetrySaveRequest();
            String requestJson = JSON.toJSONString(request);
            sapRetrySaveRequest.setParam(requestJson);
            sapRetrySaveRequest.setMsg(message);
            sapRetrySaveRequest.setMessageId(request.getMessageHeader().getMessageId());
            //请求时间戳
            sapRetrySaveRequest.setRequestTime(sdo.getExt1());
            sapRetrySaveRequest.setApiCode(SapApiCode.SAP017.getValue());
            sapRetrySaveRequest.setOutKey(sdo.getDeliveryOrderId());
            sapRetrySaveRequest.setStatus(RetryStatus.FAIL.getValue());
            sapRetryWriteService.save(sapRetrySaveRequest);
        } catch (Throwable e) {
            LOG.error("sapRetrySaveError", e);
        }
    }

    /** 检查时间戳 **/
    boolean checkModifierTime(MnSapIf017SDO datum) {
        String modifierTime = epochCacheService.get(BcOtsConstants.REDIS_CACHE_CODE(),
                DELIVERY_ORDER_CACHE_KEY + datum.getDeliveryOrderId());
        String ext = datum.getExt1();
        if (StringUtils.isNotBlank(modifierTime)) {
            String[] modifierTimeArray = modifierTime.split("\\.");
            String[] extArray = ext.split("\\.");
            if (Long.parseLong(modifierTimeArray[0]) > Long.parseLong(extArray[0])) {
                return false;
            } else if (Long.valueOf(modifierTimeArray[0]).longValue() == Long.valueOf(extArray[0]).longValue()) {
                if (Long.parseLong(modifierTimeArray[1]) >= Integer.valueOf(extArray[1]).longValue()) {
                    return false;
                }
            }
        }
        return true;
    }

    void cache(String key,String time){
        if (StringUtils.isAnyBlank(key,time)){
            return;
        }
        epochCacheService.put(BcOtsConstants.REDIS_CACHE_CODE(),
                DELIVERY_ORDER_CACHE_KEY + key,time,
                SAP_TIMESTAMP_CACHE_EXPIRE,
                TimeUnit.SECONDS);
    }

    private void handleInventory(MnSapIf017SDO sdo, List<ConsignmentOrderLine> oldLines ,
                                 List<ConsignmentOrderLine> freshLines, List<OrderLine> orderLines,
                                 Integer deliveryStatus ){
        Pair<OccupyRequest, OccupyReleaseRequest> diff = getDiff(sdo, oldLines, freshLines, orderLines);
        if (diff == null){
            return;
        }

        OccupyRequest left = diff.getLeft();
        //如果是004请求了,部分交货/已完成 就不预占
        if (left != null && CollectionUtils.isNotEmpty(left.getInvOperateLineList())){
            if (!Objects.equals(deliveryStatus, OrderStatus.PARTIAL_DELIVER.getCode()) &&
             !Objects.equals(deliveryStatus,OrderStatus.COMPLETED.getCode())){
                Result<OccupyResponse> occupy = otsUnifiedInventoryService.occupy(left);
                if (occupy == null || !occupy.isSuccess()){
                    throw new FacadeException("OTS-03-005-00-15-170");
                }
            }
        }
        OccupyReleaseRequest right = diff.getRight();
        if (right != null && CollectionUtils.isNotEmpty(right.getInvOperateLineList())){
            Result<OccupyReleaseResponse> occupyReleaseResponseResult = otsUnifiedInventoryService.occupyRelease(right);
            if (occupyReleaseResponseResult  == null || !occupyReleaseResponseResult.isSuccess()){
                throw new FacadeException("OTS-03-005-00-15-169");
            }
        }
    }

    /**
     * 销售单 根据交货单来更新平台库存预占逻辑
     **/
//    public Boolean salesOrderInvOccupy(MnSapIf017SDO datum,List<ConsignmentOrderLine> consignmentOrderLines,List<OrderLine> orderLineList) {
//            //017销售单释放库存处理逻辑
//            //历史交货单不为空，根据历史交货单释放库存
//            String modifierTime = epochCacheService.get(BcOtsConstants.REDIS_CACHE_CODE(),
//                DELIVERY_ORDER_CACHE_KEY + datum.getDeliveryOrderId());
//            boolean isSaleOrder = isSaleOrder(datum);
//            if (!isSaleOrder){
//                return false;
//            }
//        if (CollectionUtils.isNotEmpty(consignmentOrderLines)) {
//                OccupyReleaseRequest occupyReleaseRequest = new OccupyReleaseRequest();
////                ConsignmentOrder consignmentOrder = loadConsignmentOrderList.get(0);
//
//                String outDeliveryOrderNo = SapAndCrmFieldDealUtils.generateIdField(datum.getDeliveryOrderId());
//                //判断一下
//                String outerSalesOrderId = StringUtils.isNotBlank(datum.getSalesOrderId())?
//                        datum.getSalesOrderId() : datum.getStoOrderId();
//                //如果销售单存在查销售单
//                if (StringUtils.isBlank(outerSalesOrderId)){
//                    throw new FacadeException("OTS-03-005-00-15-162");
//                }
//                LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
//                loadOrderListRequest.setOuterOrderId(outerSalesOrderId);
//                Result<List<Order>> orderListResult = orderService.loadOrderList(loadOrderListRequest);
//                //如果是销售单
//                if (orderListResult != null && CollectionUtils.isNotEmpty(orderListResult.getResult())){
//                    List<Order> orderList = orderListResult.getResult();
//                    Order order = orderList.get(0);
//                    //逻辑仓库id
//                    String wareHouseCode = order.getWareHouseCode();
//                    //获取仓库档案id
//                    //获取交货单明细
////                    ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
////                    consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
////                    Result<List<ConsignmentOrderLine>> listResult = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
////                    if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
//                    if (CollectionUtils.isNotEmpty(consignmentOrderLines)){
//                        //获取 outSOLineId - quantity 理论上行不会重复
//                        Map<String, List<ConsignmentOrderLine>> lineMap = consignmentOrderLines.stream().collect(Collectors.groupingBy(ConsignmentOrderLine::getOuterSoLineId));
//                        List<InvOperateLine> invOperateLineList = Lists.newArrayList();
//                        lineMap.forEach((k,v)->{
//                            //库存释放Request
//                            InvOperateLine invOperateLine = new InvOperateLine();
//
//                            if (CollectionUtils.isEmpty(v)){
//                                //error
//                                throw new FacadeException("OTS-03-005-00-15-163");
//                            }
//                            String scItemId = v.get(0).getScItemId();
//                            if (StringUtils.isBlank(scItemId)){
//                                //error
//                                throw new FacadeException("OTS-03-005-00-15-164");
//                            }
//                            invOperateLine.setGoodsId(scItemId);
//                            invOperateLine.setDeleted(true);
//                            invOperateLine.setType("2");
//                            invOperateLine.setOutOrderId(outDeliveryOrderNo);
//                            //用缓存中上次的时间戳
//                            invOperateLine.setOutSubOrderId(modifierTime);
//                            invOperateLine.setWarehouseAreaId(wareHouseCode);
//                            //
//                            WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
//                            if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
//                                //error
//                                throw new FacadeException("OTS-03-005-00-15-165");
//                            }
//                            invOperateLine.setWarehouseId(wmsSDO.getWarehouseId());
//                            invOperateLine.setReferenceOrderId(order.getId().toString());
//                            OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
//                            orderLineLoadListRequest.setMainOrderId(order.getId().toString());
//                            orderLineLoadListRequest.setOuterOrderLineId(k);
//                            Result<List<OrderLine>> lineResult = orderLineService.loadOrderLineList(orderLineLoadListRequest);
//                            if (lineResult == null || CollectionUtils.isEmpty(lineResult.getResult())){
//                                //error
//                                throw new FacadeException("OTS-03-005-00-15-166");
//                            }
//                            OrderLine orderLine = lineResult.getResult().get(0);
//                            invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
//                            Long quantity = v.stream().mapToLong(x -> {
//                                if (StringUtils.isBlank(x.getQty())) {
//                                    return 0L;
//                                }
//                                BigDecimal bigDecimal = new BigDecimal(x.getQty().trim());
//                                return bigDecimal.movePointRight(3).longValue();
//                            }).sum();
//                            if (quantity <= 0 ){
//                                //error
//                                throw new FacadeException("OTS-03-005-00-15-167");
//                            }
//                            invOperateLine.setQuantity(quantity.toString());
//                            invOperateLineList.add(invOperateLine);
//                        });
//                        if (CollectionUtils.isEmpty(invOperateLineList)){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-168");
//                        }
//                        occupyReleaseRequest.setInvOperateLineList(invOperateLineList);
//                        LOG.info("MnSapIf017ServiceImpl_salesOrderInvOccupy,request:{},occupyReleaseRequest:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyReleaseRequest));
//                        Result<OccupyReleaseResponse> occupyReleaseResponseResult = otsUnifiedInventoryService.occupyRelease(occupyReleaseRequest);
//                        if (occupyReleaseResponseResult == null || !occupyReleaseResponseResult.isSuccess()){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-169");
//                        }
//                    }
//                }
//            }
//            //没有历史交货单 根据销售子单封装释放库存参数
//            if (CollectionUtils.isNotEmpty(orderLineList)) {
//                OccupyReleaseRequest occupyReleaseRequest = new OccupyReleaseRequest();
//                List<InvOperateLine> invOperateLineList = Lists.newArrayList();
//
//                for (OrderLine orderLine : orderLineList) {
//                    //过滤关闭的单子
//                    if (ReasonForRejectionEnum.Z1.getCode().equals(orderLine.getRefuseReasonCode())) {
//                        continue;
//                    }
//                    InvOperateLine invOperateLine = new InvOperateLine();
//                    invOperateLine.setDeleted(true);
//                    invOperateLine.setType("2");
//                    invOperateLine.setGoodsName(orderLine.getScItemTitle());
//                    invOperateLine.setGoodsId(orderLine.getScItemId());
//
//                    LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
//                    loadOrderListRequest.setId(Long.valueOf(orderLine.getMainOrderId()));
//                    Result<List<Order>> orderListResult = orderService.loadOrderList(loadOrderListRequest);
//                    if (orderListResult != null && CollectionUtils.isNotEmpty(orderListResult.getResult())) {
//                        List<Order> orderList = orderListResult.getResult();
//                        Order order = orderList.get(0);
//                        //逻辑仓库id
//                        String wareHouseCode = order.getWareHouseCode();
//                        WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
//                        if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-165");
//                        }
//                        invOperateLine.setWarehouseAreaId(wareHouseCode);
//                        invOperateLine.setWarehouseId(wmsSDO.getWarehouseId());
//                        invOperateLine.setReferenceOrderId(order.getId().toString());
//                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
//                        invOperateLine.setOutOrderId(datum.getDeliveryOrderId());
//                        invOperateLine.setOutSubOrderId(datum.getExt1().replaceAll(".",""));
//                        if (Objects.isNull(orderLine.getQuantity()) || orderLine.getQuantity() <= 0) {
//                            throw new FacadeException("OTS-03-005-00-15-167");
//                        }
//                        invOperateLine.setQuantity(String.valueOf(orderLine.getQuantity()*1000));
//                        invOperateLineList.add(invOperateLine);
//                    }
//                    occupyReleaseRequest.setInvOperateLineList(invOperateLineList);
//                    LOG.info("MnSapIf017ServiceImpl_salesOrderInvOccupy,occupyReleaseRequest:{}",JSON.toJSONString(occupyReleaseRequest));
//                    Result<OccupyReleaseResponse> occupyReleaseResponseResult = otsUnifiedInventoryService.occupyRelease(occupyReleaseRequest);
//                    if (occupyReleaseResponseResult == null || !occupyReleaseResponseResult.isSuccess()){
//                        //error
//                        throw new FacadeException("OTS-03-005-00-15-169");
//                    }
//                }
//
//            }
//
//
//
//
//            //017销售单预占库存逻辑
//            String outDeliveryOrderNo = datum.getDeliveryOrderId();
//            //销售单库存预占请求参数
//            OccupyRequest occupyRequest = new OccupyRequest();
//            //017销售单预占库存处理逻辑：
//            //查询017创建的交货单
//            //根据交货单中外部销售单号查销售单 确保该交货单绑定的是销售单据 调拨单不处理
//            //根据销售单号查交货单明细 明细信息封装释放、预占库存参数
//            ConsignmentOrderLoadListRequest consignmentOrderLoadListRequest = new ConsignmentOrderLoadListRequest();
//            consignmentOrderLoadListRequest.setOuterDeliveryOrderId(outDeliveryOrderNo);
//            Result<List<ConsignmentOrder>> loadConsignmentOrderListResult = consignmentOrderService.loadConsignmentOrderList(consignmentOrderLoadListRequest);
//            //交货单需要存在
//            if (loadConsignmentOrderListResult == null || CollectionUtils.isEmpty(loadConsignmentOrderListResult.getResult())){
//                throw new FacadeException("OTS-03-005-00-15-160");
//            }
//            ConsignmentOrder consignmentOrder = loadConsignmentOrderListResult.getResult().get(0);
//
//            //判断一下
//            String outerSalesOrderId = StringUtils.isNotBlank(consignmentOrder.getOuterSalesOrderId())?
//                    consignmentOrder.getOuterSalesOrderId() : consignmentOrder.getOuterStoOrderId();
//            //如果销售单存在查销售单
//            if (StringUtils.isBlank(outerSalesOrderId)){
//                throw new FacadeException("OTS-03-005-00-15-162");
//            }
//            LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
//            loadOrderListRequest.setOuterOrderId(outerSalesOrderId);
//            Result<List<Order>> orderListResult = orderService.loadOrderList(loadOrderListRequest);
//            //如果是销售单
//            if (orderListResult != null && CollectionUtils.isNotEmpty(orderListResult.getResult())){
//                List<Order> orderList = orderListResult.getResult();
//                Order order = orderList.get(0);
//                //逻辑仓库id
//                String wareHouseCode = order.getWareHouseCode();
//                //获取仓库档案id
//                //获取交货单明细
//                ConsignmentOrderLineLoadListRequest consignmentOrderLineLoadListRequest = new ConsignmentOrderLineLoadListRequest();
//                consignmentOrderLineLoadListRequest.setConsignmentOrderId(consignmentOrder.getId().toString());
//                Result<List<ConsignmentOrderLine>> listResult = consignmentOrderLineService.loadConsignmentOrderLineList(consignmentOrderLineLoadListRequest);
//                if (listResult != null && CollectionUtils.isNotEmpty(listResult.getResult())){
//                    //获取 outSOLineId - quantity 理论上行不会重复
//                    Map<String, List<ConsignmentOrderLine>> lineMap = listResult.getResult().stream().collect(Collectors.groupingBy(ConsignmentOrderLine::getOuterSoLineId));
//                    List<InvOperateLine> invOperateLineList = Lists.newArrayList();
//                    lineMap.forEach((k,v)->{
//                        //库存释放Request
//                        InvOperateLine invOperateLine = new InvOperateLine();
//
//                        if (CollectionUtils.isEmpty(v)){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-163");
//                        }
//                        String scItemId = v.get(0).getScItemId();
//                        if (StringUtils.isBlank(scItemId)){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-164");
//                        }
//                        invOperateLine.setGoodsId(scItemId);
//                        invOperateLine.setDeleted(false);
//                        invOperateLine.setType("2");
//                        invOperateLine.setOutOrderId(outDeliveryOrderNo);
//                        //发现没有时间戳 用交货单号代替了.
//                        invOperateLine.setOutSubOrderId(datum.getExt1());
//                        invOperateLine.setWarehouseAreaId(wareHouseCode);
//
//                        WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
//                        if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-165");
//                        }
//                        invOperateLine.setWarehouseId(wmsSDO.getWarehouseId());
//                        invOperateLine.setReferenceOrderId(order.getId().toString());
//                        OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
//                        orderLineLoadListRequest.setMainOrderId(order.getId().toString());
//                        orderLineLoadListRequest.setOuterOrderLineId(k);
//                        Result<List<OrderLine>> lineResult = orderLineService.loadOrderLineList(orderLineLoadListRequest);
//                        if (lineResult == null || CollectionUtils.isEmpty(lineResult.getResult())){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-166");
//                        }
//                        OrderLine orderLine = lineResult.getResult().get(0);
//                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
//                        Long quantity = v.stream().mapToLong(x -> {
//                            if (StringUtils.isBlank(x.getQty())) {
//                                return 0L;
//                            }
//                            BigDecimal bigDecimal = new BigDecimal(x.getQty().trim());
//                            return bigDecimal.movePointRight(3).longValue();
//                        }).sum();
//                        if (quantity <= 0 ){
//                            //error
//                            throw new FacadeException("OTS-03-005-00-15-167");
//                        }
//                        invOperateLine.setQuantity(quantity.toString());
//                        invOperateLineList.add(invOperateLine);
//                    });
//                    if (CollectionUtils.isEmpty(invOperateLineList)){
//                        //error
//                        throw new FacadeException("OTS-03-005-00-15-168");
//                    }
//                    occupyRequest.setInvOperateLineList(invOperateLineList);
//                    LOG.info("MnSapIf017ServiceImpl_salesOrderInvOccupy,request:{},occupyRequest:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(occupyRequest));
//                    Result<OccupyResponse> occupyResponseResult = otsUnifiedInventoryService.occupy(occupyRequest);
//
//                    if (occupyResponseResult == null || !occupyResponseResult.isSuccess()){
//                        //error
//                        throw new FacadeException("OTS-03-005-00-15-169");
//                    }
//                }
//            }
//
//        return true;
//    }

    private static boolean isSaleOrder(MnSapIf017SDO datum){
        //013接口会同步特殊的销售单，判断ext=ZORO且销售组织是1171的交货单，修改为销售订单类型的交货单
        if ((StringUtils.isNotBlank(datum.getExt())&&saleOrderExtList.contains(datum.getExt()))&&(
                StringUtils.isNotBlank(datum.getSalesOrgId())&& SPEC_ORG.equalsIgnoreCase(datum.getSalesOrgId())
        )){
            return true;
        }
        //退货不预占库存
        if (returnGoodsExtList.contains(datum.getExt())){
            return false;
        }
        if (StringUtils.isNotBlank(datum.getSalesOrderId())){
            return true;
        }
        return false;
    }

    //获取差异
    private Pair<OccupyRequest,OccupyReleaseRequest> getDiff(MnSapIf017SDO sdo, List<ConsignmentOrderLine> oldLines ,
                                                             List<ConsignmentOrderLine> freshLines, List<OrderLine> orderLines){
        Pair<OccupyRequest,OccupyReleaseRequest> pair = null;
        //判断如果是交货单创建
        List<InvOperateLine> occupyInvOperateLineList = Lists.newArrayList();
//        OccupyOccupyReleaseRequest occupyReleaseRequest = new OccupyOccupyReleaseRequest();
        OccupyRequest occupyRequest = new OccupyRequest();
        OccupyReleaseRequest occupyReleaseRequest = new OccupyReleaseRequest();
        List<InvOperateLine> occupyReleaseInvOperateLineList = Lists.newArrayList();
        String salesOrderId = sdo.getSalesOrderId();
        String time = sdo.getExt1();
        String outDeliveryOrderNo = SapAndCrmFieldDealUtils.generateIdField(sdo.getDeliveryOrderId());
        LoadOrderListRequest loadOrderListRequest = new LoadOrderListRequest();
        loadOrderListRequest.setOuterOrderId(salesOrderId);
        Result<List<Order>> listResult = orderService.loadOrderList(loadOrderListRequest);
        if (listResult == null || CollectionUtils.isEmpty(listResult.getResult())){
            throw new FacadeException("OTS-03-005-00-15-166");
        }
        Order order = listResult.getResult().get(0);
        String wareHouseCode = order.getWareHouseCode();
        WmsSDO wmsSDO = InfoUtil.getWmsSDO(wareHouseCode);
        if (StringUtils.isBlank(wmsSDO.getWarehouseId())){
            //error
            LOG.error("MnSapIf017ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(wmsSDO));
            throw new FacadeException("OTS-03-005-00-15-165");
        }
        String warehouseId = wmsSDO.getWarehouseId();

        //要获取到预占的量 和释放的量
        if (CollectionUtils.isNotEmpty(orderLines)){
            //和原先的订单明细对比 需要注意换货的, 可以在开头进行排除
            for (ConsignmentOrderLine freshLine : freshLines) {
                List<OrderLine> sameLines = orderLines.stream().filter(x -> compare(freshLine.getOuterSoLineId(), x.getOuterOrderLineId()))
                        .collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(sameLines)){
                    OrderLine orderLine = sameLines.get(0);
                    InvOperateLine invOperateLine = new InvOperateLine();
                    Long quantity = getDiff(orderLine.getQuantity(), freshLine.getQty());
                    Long reverseQuantity = getDiff(freshLine.getQty(), orderLine.getQuantity());
                    if (quantity > 0){
                        invOperateLine.setQuantity(quantity.toString());
                        invOperateLine.setWarehouseId(warehouseId);
                        invOperateLine.setWarehouseAreaId(wareHouseCode);
                        invOperateLine.setType("2");
                        invOperateLine.setReferenceOrderId(order.getId().toString());
                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                        invOperateLine.setOutOrderId(outDeliveryOrderNo);
                        invOperateLine.setOutSubOrderId(time);
                        invOperateLine.setDeleted(true);
                        invOperateLine.setGoodsId(orderLine.getScItemId());
                        occupyReleaseInvOperateLineList.add(invOperateLine);
                    }else if (quantity < 0){
                        invOperateLine.setQuantity(reverseQuantity.toString());
                        invOperateLine.setWarehouseId(warehouseId);
                        invOperateLine.setWarehouseAreaId(wareHouseCode);
                        invOperateLine.setType("2");
                        invOperateLine.setReferenceOrderId(order.getId().toString());
                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                        invOperateLine.setOutOrderId(outDeliveryOrderNo);
                        invOperateLine.setOutSubOrderId(time);
                        invOperateLine.setDeleted(false);
                        invOperateLine.setGoodsId(orderLine.getScItemId());
                        occupyInvOperateLineList.add(invOperateLine);
                    }else {
                        continue;
                    }
                }
            }
            //这里不需要反向比较,删除的时候 会释放预占 orderLine里需要去掉行关闭的

        }else if (CollectionUtils.isNotEmpty(oldLines)){
            //获取 新交货单和老交货单的差异
            for (ConsignmentOrderLine freshLine : freshLines) {
                List<ConsignmentOrderLine> sameLines = oldLines.stream().filter(x -> Objects.equals(SapAndCrmFieldDealUtils.generateIdField(x.getOuterSoLineId()),
                        SapAndCrmFieldDealUtils.generateIdField(freshLine.getOuterSoLineId()))).collect(Collectors.toList());
                //行相同 比较数量
                if (CollectionUtils.isNotEmpty(sameLines)){
                    ConsignmentOrderLine consignmentOrderLine = sameLines.get(0);
                    InvOperateLine invOperateLine = new InvOperateLine();
                    Long quantity = getDiff(consignmentOrderLine.getQty(),freshLine.getQty());
                    Long reverseQuantity = getDiff(freshLine.getQty(),consignmentOrderLine.getQty());
                    if (quantity > 0){
                        OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                        orderLineLoadListRequest.setOuterOrderLineId(SapAndCrmFieldDealUtils.generateIdField(freshLine.getOuterSoLineId()));
                        orderLineLoadListRequest.setMainOrderId(order.getId().toString());
                        Result<List<OrderLine>> orderLineList = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                        if (orderLineList == null || CollectionUtils.isEmpty(orderLineList.getResult())){
                            LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLineLoadListRequest));
                            throw new FacadeException("OTS-03-005-00-15-166");
                        }
                        OrderLine orderLine = orderLineList.getResult().get(0);
                        invOperateLine.setQuantity(quantity.toString());
                        invOperateLine.setWarehouseId(warehouseId);
                        invOperateLine.setWarehouseAreaId(wareHouseCode);
                        invOperateLine.setType("2");
                        invOperateLine.setReferenceOrderId(order.getId().toString());
                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                        invOperateLine.setOutOrderId(outDeliveryOrderNo);
                        invOperateLine.setOutSubOrderId(time);
                        invOperateLine.setDeleted(false);
                        String scItemId = orderLine.getScItemId();
                        if (StringUtils.isBlank(scItemId)){
                            //error
                            LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLine));
                            throw new FacadeException("OTS-03-005-00-15-164");
                        }
                        invOperateLine.setGoodsId(scItemId);
                        occupyInvOperateLineList.add(invOperateLine);
                    }else if (quantity <0){
                        OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                        orderLineLoadListRequest.setOuterOrderLineId(SapAndCrmFieldDealUtils.generateIdField(freshLine.getOuterSoLineId()));
                        orderLineLoadListRequest.setMainOrderId(order.getId().toString());
                        Result<List<OrderLine>> orderLineList = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                        if (orderLineList == null || CollectionUtils.isNotEmpty(orderLines)){
                            LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLines));
                            throw new FacadeException("OTS-03-005-00-15-166");
                        }
                        OrderLine orderLine = orderLineList.getResult().get(0);
                        invOperateLine.setQuantity(reverseQuantity.toString());
                        invOperateLine.setWarehouseId(warehouseId);
                        invOperateLine.setWarehouseAreaId(wareHouseCode);
                        invOperateLine.setType("2");
                        invOperateLine.setReferenceOrderId(order.getId().toString());
                        invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                        invOperateLine.setOutOrderId(outDeliveryOrderNo);
                        invOperateLine.setOutSubOrderId(time);
                        invOperateLine.setDeleted(true);
                        String scItemId = consignmentOrderLine.getScItemId();
                        if (StringUtils.isBlank(scItemId)){
                            LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(consignmentOrderLine));
                            throw new FacadeException("OTS-03-005-00-15-164");
                        }
                        invOperateLine.setGoodsId(scItemId);
                        occupyReleaseInvOperateLineList.add(invOperateLine);
                    }else {
                        continue;
                    }


                }else {
                    //如果没有这行 需要释放
                    InvOperateLine invOperateLine = new InvOperateLine();
                    OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                    orderLineLoadListRequest.setOuterOrderLineId(SapAndCrmFieldDealUtils.generateIdField(freshLine.getOuterSoLineId()));
                    orderLineLoadListRequest.setMainOrderId(order.getId().toString());
                    Result<List<OrderLine>> orderLineList = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                    if (orderLineList == null || CollectionUtils.isEmpty(orderLineList.getResult())){
                        LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLineLoadListRequest));
                        throw new FacadeException("OTS-03-005-00-15-166");
                    }
                    OrderLine orderLine = orderLineList.getResult().get(0);
                    String qty = freshLine.getQty();
                    Long quantity;
                    if (StringUtils.isBlank(qty)){
                        quantity = 0L;
                    }else {
                        quantity =  new BigDecimal(qty.trim()).movePointRight(3).longValue();
                    }
                    if (quantity <= 0){
                        LOG.error("MnSapIf017ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(freshLine));
                        throw new FacadeException("OTS-03-005-00-15-167");
                    }
                    invOperateLine.setQuantity(quantity.toString());
                    invOperateLine.setWarehouseId(warehouseId);
                    invOperateLine.setWarehouseAreaId(wareHouseCode);
                    invOperateLine.setType("2");
                    invOperateLine.setReferenceOrderId(order.getId().toString());
                    invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                    invOperateLine.setOutOrderId(outDeliveryOrderNo);
                    invOperateLine.setOutSubOrderId(time);
                    invOperateLine.setDeleted(false);
                    String scItemId = orderLine.getScItemId();
                    if (StringUtils.isBlank(scItemId)){
                        //error
                        LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLine));
                        throw new FacadeException("OTS-03-005-00-15-164");
                    }
                    invOperateLine.setGoodsId(scItemId);
                    occupyInvOperateLineList.add(invOperateLine);
                }
            }
            //
            for (ConsignmentOrderLine oldLine : oldLines) {
                List<ConsignmentOrderLine> sameLines = freshLines.stream().filter(x -> Objects.equals(SapAndCrmFieldDealUtils.generateIdField(x.getOuterSoLineId()),
                        SapAndCrmFieldDealUtils.generateIdField(oldLine.getOuterSoLineId()))).collect(Collectors.toList());
                //即需要释放这行 重复的已经在上面处理了   老的234  新的345
                if (CollectionUtils.isEmpty(sameLines)){

                    InvOperateLine invOperateLine = new InvOperateLine();
                    OrderLineLoadListRequest orderLineLoadListRequest = new OrderLineLoadListRequest();
                    orderLineLoadListRequest.setMainOrderId(order.getId().toString());
                    orderLineLoadListRequest.setOuterOrderLineId(SapAndCrmFieldDealUtils.generateIdField(oldLine.getOuterSoLineId()));
                    Result<List<OrderLine>> orderLineList = orderLineService.loadOrderLineList(orderLineLoadListRequest);
                    if (orderLineList == null || CollectionUtils.isEmpty(orderLineList.getResult())){
                        LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLineLoadListRequest));
                        throw new FacadeException("OTS-03-005-00-15-166");
                    }
                    OrderLine orderLine = orderLineList.getResult().get(0);
                    String qty = oldLine.getQty();
                    Long quantity;
                    if (StringUtils.isBlank(qty)){
                        quantity = 0L;
                    }else {
                        quantity = new BigDecimal(qty.trim()).movePointRight(3).longValue();
                    }
                    if (quantity <= 0 ){
                        LOG.error("MnSapIf017ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLine));
                        throw new FacadeException("OTS-03-005-00-15-167");
                    }
                    invOperateLine.setQuantity(quantity.toString());
                    invOperateLine.setWarehouseId(warehouseId);
                    invOperateLine.setWarehouseAreaId(wareHouseCode);
                    invOperateLine.setType("2");
                    invOperateLine.setReferenceSubOrderId(orderLine.getId().toString());
                    invOperateLine.setReferenceOrderId(order.getId().toString());
                    invOperateLine.setOutOrderId(outDeliveryOrderNo);
                    invOperateLine.setDeleted(true);
                    String scItemId = orderLine.getScItemId();
                    if (StringUtils.isBlank(scItemId)){
                        //error
                        LOG.error("MnSapIf018ServiceImpl_occupyRelease_Error,request:{},consignmentOrderLine:{}",JSON.toJSONString(outDeliveryOrderNo),JSON.toJSONString(orderLine));
                        throw new FacadeException("OTS-03-005-00-15-164");
                    }
                    invOperateLine.setGoodsId(scItemId);
                    occupyReleaseInvOperateLineList.add(invOperateLine);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(occupyInvOperateLineList) || CollectionUtils.isNotEmpty(occupyReleaseInvOperateLineList)){
            occupyRequest.setInvOperateLineList(occupyInvOperateLineList);
            occupyReleaseRequest.setInvOperateLineList(occupyReleaseInvOperateLineList);
            return Pair.of(occupyRequest,occupyReleaseRequest);
        }
        return null;
    }

    private static boolean isEqualNumber(String old,String fresh){
        BigDecimal oldBigDecimal = new BigDecimal(old.trim()).movePointRight(3);
        BigDecimal freshBigDecimal = new BigDecimal(fresh.trim()).movePointRight(3);
        return oldBigDecimal.longValue() == freshBigDecimal.longValue();
    }
    private static Long getDiff(String old,String fresh){
        BigDecimal oldBigDecimal = new BigDecimal(old.trim()).movePointRight(3);
        BigDecimal freshBigDecimal = new BigDecimal(fresh.trim()).movePointRight(3);
        return freshBigDecimal.subtract(oldBigDecimal).longValue();
    }
    private static Long getDiff(Integer old,String fresh){
        if (old == null){
            old = 0;
        }
        BigDecimal bigDecimal = new BigDecimal(old).movePointRight(3);
        BigDecimal decimal = new BigDecimal(fresh.trim()).movePointRight(3);
        return bigDecimal.subtract(decimal).longValue();
    }
    private static Long getDiff(String fresh,Integer old){
        if (old == null){
            old = 0;
        }
        BigDecimal bigDecimal = new BigDecimal(old).movePointRight(3);
        BigDecimal decimal = new BigDecimal(fresh.trim()).movePointRight(3);
        return decimal.subtract(bigDecimal).longValue();
    }

    private static boolean compare(String oldLineId,String freshLineId){
        return Objects.equals(SapAndCrmFieldDealUtils.generateIdField(oldLineId),
                SapAndCrmFieldDealUtils.generateIdField(freshLineId));
    }
}
